package net.hn.hnms.biz.activiti.controller;


import cn.hutool.core.util.ObjectUtil;
import com.aspose.words.Document;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.hn.hnms.biz.activiti.listener.DeleteTaskCommand;
import net.hn.hnms.biz.activiti.repository.MyProcessRepository;
import net.hn.hnms.biz.activiti.domain.*;
import net.hn.hnms.biz.api.mine.RemoteMineInfoService;
import net.hn.hnms.biz.api.mine.model.WeChartBaseMessage;
import net.hn.hnms.sys.common.core.constant.Constants;
import net.hn.hnms.sys.common.core.domain.R;
import net.hn.hnms.sys.common.core.domain.ResponsePage;
import net.hn.hnms.sys.common.core.exception.HuaNengException;
import net.hn.hnms.sys.common.core.exception.ServiceException;
import net.hn.hnms.sys.common.log.annotation.Log;
import net.hn.hnms.sys.common.log.enums.BusinessType;
import net.hn.hnms.sys.common.satoken.config.AutoSetMineCode;
import net.hn.hnms.sys.common.satoken.utils.LoginHelper;
import net.hn.hnms.sys.file.api.RemoteFileService;
import net.hn.hnms.sys.file.api.domain.SysFile;
import net.hn.hnms.sys.system.api.RemoteUserService;
import net.hn.hnms.sys.system.api.model.UserVo;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.*;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.*;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.HistoricFormPropertyEntityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 智呈物联 pansx
 * 2021/9/24 16:55
 * 1.0 version
 */
@RestController
@RequestMapping("act/api")
@Api(value = "流程接口", tags = "流程接口")
@AllArgsConstructor
@Slf4j
public class ActivitiController {


    RepositoryService repositoryService;

    RuntimeService runtimeService;

    TaskService taskService;

    HistoryService historyService;

    ProcessEngine processEngine;

    ProcessEngineConfiguration processEngineConfiguration;
    FormService formService;
    //根据用户id获取用户信息
    RemoteUserService remoteUserService;

    RemoteMineInfoService remoteMineInfoService;
    MyProcessRepository myProcessRepository;


    @Resource
    private RemoteFileService remoteFileService;


    @PostMapping(value = "deploy", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "部署流程", position = 1)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "bpmn文件", name = "bpmn", dataTypeClass = File.class),
            @ApiImplicitParam(value = "image文件", name = "image", dataTypeClass = File.class)
    })
    @Log(title = "添加部署流程", businessType = BusinessType.INSERT)
    public R<DeploymentDto> deploy(@RequestPart @RequestParam(value = "bpmn") MultipartFile bpmn,
                                   @RequestPart @RequestParam(value = "image") MultipartFile image, DeploymentDto deploymentDto) {

        DeploymentBuilder builder = repositoryService.createDeployment();
        if (bpmn == null) {
            return R.fail("文件无效");
        }

        if (bpmn != null) {
            String originalFilename = bpmn.getOriginalFilename();
            if (!originalFilename.endsWith(".bpmn")) {
                return R.fail("请上传bpmn文件格式");
            }
            try {
                InputStream inputStream = bpmn.getInputStream();
                builder.addInputStream(originalFilename, inputStream);
            } catch (IOException e) {
                return R.fail("bpmn文件读取异常");
            }
        } else {
            return R.fail("未上传bpmn文件");
        }

        if (image != null) {
            String originalFilename = image.getOriginalFilename();
            if (originalFilename.endsWith(".png") || originalFilename.endsWith(".jpg")) {
                InputStream inputStream = null;
                try {
                    inputStream = image.getInputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                builder.addInputStream(originalFilename, inputStream);
            }
        }
        Deployment deploy = builder.name(deploymentDto.getName()).key(deploymentDto.getKey()).deploy();
        deploymentDto.setID(deploy.getId());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
        deploymentDto.setProcessDefinitionId(processDefinition.getId());
        return R.ok(deploymentDto);
    }

    @DeleteMapping("deldeploy/{id}")
    @ApiOperation(value = "删除部署流程")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "isForce", value = "是否强制删除", defaultValue = "false")
    })
    @Log(title = "删除部署流程", businessType = BusinessType.DELETE)
    public R delDeploy(@PathVariable @ApiParam(required = true, name = "id", value = "流程定义id") String id,
                       boolean isForce) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
        if (isForce) {
            repositoryService.deleteDeployment(processDefinition.getDeploymentId(), isForce);

            return R.ok("删除成功");
        } else {
            try {
                repositoryService.deleteDeployment(processDefinition.getDeploymentId());
                return R.ok("删除成功");
            } catch (PersistenceException e) {
                return R.fail("删除失败，存在未完成的流程。");
            }
        }

    }

    @GetMapping("getNodeFormByProcessDefinitionId")
    @ApiOperation(value = "根据流程定义获取初始化节点填报项")
    @Log(title = "查询初始化节点填报项", businessType = BusinessType.OTHER)
    public R<List<FormProperty>> getStartFormByProcessDefinitionId(String processDefinitionId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        List<UserTask> flowElementsOfType = bpmnModel.getProcesses().get(0).findFlowElementsOfType(UserTask.class);
        List<FormProperty> formProperties = flowElementsOfType.get(0).getFormProperties();
        return R.ok(formProperties);
    }

    @PostMapping("startProcess")
    @ApiOperation(value = "启动流程", notes = "创建一个流程实例")
    @Log(title = "启动流程", businessType = BusinessType.INSERT)
    @AutoSetMineCode
    public R<ProcessInstanceDto> startProcess(@RequestBody @Validated StartProcessVo startProcessVo) {
        Long userId = LoginHelper.getUserId();
        String processDefinitionId = startProcessVo.getProcessDefinitionId();
        for (Map.Entry<String, String> entry : startProcessVo.getFormMap().entrySet()) {
            if (entry.getKey().startsWith("process_"))
                startProcessVo.getProcessParams().put(entry.getKey(), entry.getValue());
            if (entry.getKey().startsWith("node_"))
                startProcessVo.getNodeParams().put(entry.getKey(), entry.getValue());
        }

        //拦截formMap 里面的编码
        Map<String, String> formMap = startProcessVo.getFormMap();
        //获取编码
        R<String> codeByProcessDefinitionId = this.getCodeByProcessDefinitionId(startProcessVo.getProcessDefinitionId());
        formMap.put("code_input", codeByProcessDefinitionId.getData());
        startProcessVo.setFormMap(formMap);


        String businessKey = startProcessVo.getBusinessKey();
        Map<String, Object> processParams = startProcessVo.getProcessParams();
        String name = startProcessVo.getFormMap().get("processName_input");
        Map<String, Object> nodeParams = startProcessVo.getNodeParams();
        processParams.put("assignee", userId);
        String key = startProcessVo.getKey();
        ProcessInstance processInstance = null;
        Authentication.setAuthenticatedUserId(userId.toString());
        if (StringUtils.isNotBlank(processDefinitionId)) {
            processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessKey, processParams);
        } else if (StringUtils.isNotBlank(key)) {
            processInstance = runtimeService.startProcessInstanceByKey(key, businessKey, processParams);
        } else {
            return R.fail("未获取到对应的流程");
        }

        if (StringUtils.isNotBlank(name)) {
            runtimeService.setProcessInstanceName(processInstance.getId(), name);
        }
        List<org.activiti.engine.task.Task> list = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
        list.forEach(s -> {
            taskService.setVariablesLocal(s.getId(), nodeParams);
            formService.saveFormData(s.getId(), startProcessVo.getFormMap());
            taskService.setAssignee(s.getId(), userId.toString());
            if (startProcessVo.isNextNode()) {
                taskService.complete(s.getId());

            }
        });
        //推送消息
        if (startProcessVo.isNextNode()) {
            List<Task> list1 = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
            List<String> toUser = new ArrayList();
            for (int i = 0; i < list1.size(); i++) {
                if (StringUtils.isNotBlank(list1.get(i).getAssignee())) {
                    UserVo userById = remoteUserService.getUserById(Long.parseLong(list1.get(i).getAssignee()));
                    if (userById != null) {
                        toUser.add(userById.getUserName());
                    }
                }
            }
            if (!toUser.isEmpty()) {
                WeChartBaseMessage msg = new WeChartBaseMessage();
                String content = "有待您审批的流程——" + name + ",请登陆系统后审批。";
                msg.setContent(content);
                msg.setPassword("hn@2022");
                msg.setToUsers(StringUtils.join(toUser, ","));
                try {
                    remoteMineInfoService.sendBaseMessage(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
        try {
            HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
            processDetail(instance, startProcessVo.getMineCode());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("流程保存业务表异常：" + e.getMessage());
        }
        return R.ok("操作成功");
    }

    @GetMapping("getNodeFormByTaskId")
    @ApiOperation(value = "获取某一节点from参数")
    @Log(title = "查询节点from参数", businessType = BusinessType.OTHER)
    public R<TaskStatusVo> getNodeForm(String taskId) {
        TaskStatusVo vo = new TaskStatusVo();
        TaskFormData taskFormData = formService.getTaskFormData(taskId);
        List<org.activiti.engine.form.FormProperty> formProperties = taskFormData.getFormProperties();
        vo.setFormProperties(formProperties);
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (historicTaskInstance.getEndTime() != null) {
            vo.setEnd(true);
        } else {
            vo.setEnd(false);
        }
        return R.ok(vo);
    }

    @GetMapping("queryTaskByUser")
    @ApiOperation(value = "待办任务", notes = "待办任务")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "definitionId", value = "流程定义id"),
    })
    @Log(title = "查询待办任务", businessType = BusinessType.OTHER)
    public R<ResponsePage<TaskDto>> queryTaskByUser(String definitionId, @RequestParam(defaultValue = "0") int pageNum, @RequestParam(defaultValue = "20") int pageSize) {

        TaskQuery taskQuery = taskService.createTaskQuery();
        if (StringUtils.isNotBlank(definitionId)) {
            taskQuery.processDefinitionId(definitionId);
        }
        String assignee = LoginHelper.getUserId().toString();
        long count = taskQuery.taskAssignee(assignee).count();
        List<Task> tasks = new ArrayList<>();
        if (count == 0) {
            return R.ok(new ResponsePage<TaskDto>(tasks, count));
        }
        tasks = taskQuery.taskAssignee(assignee).orderByTaskCreateTime().desc().listPage(pageNum < 0 ? 0 : (pageNum * pageSize), pageSize);
        List<TaskDto> list = new ArrayList<>();
        tasks.forEach(s -> {
            TaskDto dto = new TaskDto();
            BeanUtils.copyProperties(s, dto);
            if (dto.getName().equals("发起") || dto.getName().equals("发起审批") || dto.getName().equals("技术负责人填报")) {
                dto.setName("暂存中待发起审批");
            }
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(s.getProcessInstanceId()).singleResult();
            dto.setBusinessKey(processInstance.getBusinessKey());
            dto.setProcessInstanceName(processInstance.getName());
            UserVo userById = remoteUserService.getUserById(Long.parseLong(processInstance.getStartUserId()));
            dto.setStartUser(userById.getNickName());
            list.add(dto);
        });
        return R.ok(new ResponsePage<TaskDto>(list, count));
    }

    @GetMapping("getProcessImg")
    @ApiOperation(value = "获取流程图")
    @Log(title = "查询流程图", businessType = BusinessType.OTHER)
    public R getProcessImg(String processDefinitionId) throws IOException {
        byte[] bytes = null;
        InputStream inputStream = null;
        try {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
            ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
            inputStream = processDiagramGenerator.generateDiagram(bpmnModel, "jpg", new ArrayList<>(), new ArrayList<>(), "宋体", "微软雅黑", "黑体", null, 1.0);
            bytes = IOUtils.toByteArray(inputStream);
            String encoded = Base64.getEncoder().encodeToString(bytes);
            return R.ok("", encoded);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return R.fail("生成流程图失败");
    }

    @GetMapping("getProcessInstancesImg")
    @ApiOperation(value = "获取流程跟踪图")
    @Log(title = "查询流程跟踪图", businessType = BusinessType.OTHER)
    public R getProcessInstancesImg(String processInstanceId) throws IOException {
        byte[] bytes = null;
        InputStream inputStream = null;
        try {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId).singleResult();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
            //获取已经执行的节点
            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId)
                    .orderByHistoricActivityInstanceId().asc().list();
            //已经执行的id集合

            List<String> executedActivityIdList = list.stream().map(HistoricActivityInstance::getActivityId)
                    .collect(Collectors.toList());
            //已执行flow的集和
            List<String> executedFlowIdList = executedFlowIdList(bpmnModel, list);

            ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
            inputStream = processDiagramGenerator.generateDiagram(bpmnModel, "jpg", executedActivityIdList, executedFlowIdList, "宋体", "微软雅黑", "黑体", null, 1.0);
            bytes = IOUtils.toByteArray(inputStream);
            String encoded = Base64.getEncoder().encodeToString(bytes);
            return R.ok("", encoded);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return R.fail("生成流程图失败");
    }

    private static List<String> executedFlowIdList(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstanceList) {
        List<String> executedFlowIdList = new ArrayList<>();
        for (int i = 0; i < historicActivityInstanceList.size() - 1; i++) {
            HistoricActivityInstance hai = historicActivityInstanceList.get(i);
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(hai.getActivityId());
            List<SequenceFlow> sequenceFlows = flowNode.getOutgoingFlows();
            if (sequenceFlows.size() > 1) {
                HistoricActivityInstance nextHai = historicActivityInstanceList.get(i + 1);
                sequenceFlows.forEach(sequenceFlow -> {
                    if (sequenceFlow.getTargetFlowElement().getId().equals(nextHai.getActivityId())) {
                        executedFlowIdList.add(sequenceFlow.getId());
                    }
                });
            } else {
                if (!sequenceFlows.isEmpty()) {
                    executedFlowIdList.add(sequenceFlows.get(0).getId());
                }
            }
        }
        return executedFlowIdList;
    }

    @PostMapping("examine/{taskId}")
    @ApiOperation(value = "完成任务", notes = "完成任务")
    @Log(title = "完成任务", businessType = BusinessType.UPDATE)
    @AutoSetMineCode
    public R examine(@PathVariable @ApiParam(required = true, name = "taskId", value = "任务id") String taskId,
                     @RequestBody ExamineVo examineVo, String mineCode) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return R.fail("未找到对应的任务");
        }
        if (task.isSuspended()) {
            return R.fail("流程被挂起");
        }
        Long userId = LoginHelper.getUserId();
        boolean equals = userId.toString().equals(task.getAssignee());
        if (!equals) {
            return R.fail("无权处理");
        }
        formService.saveFormData(taskId, examineVo.getFormMap());
        taskService.setVariablesLocal(taskId, examineVo.getNodeParams());
        if (examineVo.isNextNode()) {
            taskService.complete(taskId, examineVo.getProcessParams());
        }

        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();

        if (Objects.isNull(historicProcessInstance.getEndTime())) {
            List<Task> list = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
            List<Map> tasks = new ArrayList<>();
            if (examineVo.isNextNode()) {
                List<String> toUser = new ArrayList();
                for (int i = 0; i < list.size(); i++) {
                    if (StringUtils.isNotBlank(list.get(i).getAssignee())) {
                        UserVo userById = remoteUserService.getUserById(Long.parseLong(list.get(i).getAssignee()));
                        if (userById != null) {
                            toUser.add(userById.getUserName());
                        }
                    }
                }
                if (!toUser.isEmpty()) {
                    WeChartBaseMessage msg = new WeChartBaseMessage();
                    String content = "有待您审批的流程——" + historicProcessInstance.getName() + ",请登陆系统后审批。";
                    msg.setContent(content);
                    msg.setPassword("hn@2022");
                    msg.setToUsers(StringUtils.join(toUser, ","));
                    try {
                        remoteMineInfoService.sendBaseMessage(msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }
            list.forEach(s -> {
                if (!task.getTaskDefinitionKey().equals(s.getTaskDefinitionKey())) {
                    tasks.add(new HashMap() {{
                        put("taskId", s.getId());
                        put("name", s.getName());
                        put("assignee", s.getAssignee());
                    }});
                }
            });
            try {
                processDetail(historicProcessInstance, mineCode);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("流程保存业务表异常：" + e.getMessage());
            }
            return R.ok(new HashMap() {{
                put("processInstanceStatus", "进行中");
                put("businessKey", historicProcessInstance.getBusinessKey());
                put("tasks", tasks);
            }});
        } else {
            UserVo userById = remoteUserService.getUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
            if (userById != null) {
                WeChartBaseMessage msg = new WeChartBaseMessage();
                String content = "您发起的流程——" + historicProcessInstance.getName() + ",已完成审批。";
                msg.setContent(content);
                msg.setPassword("hn@2022");
                msg.setToUsers(userById.getUserName());
                try {
                    remoteMineInfoService.sendBaseMessage(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            try {
                processDetail(historicProcessInstance, mineCode);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("流程保存业务表异常：" + e.getMessage());
            }
            return R.ok(new HashMap() {{
                put("processInstanceStatus", "已结束");
                put("businessKey", historicProcessInstance.getBusinessKey());
            }});
        }

    }

    @GetMapping("suspendProcessDefinitionById")
    @ApiOperation(value = "流程挂起")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", required = true),
            @ApiImplicitParam(name = "suspendProcessInstances", value = "是否挂起流程实例")
    })
    @Log(title = "流程挂起", businessType = BusinessType.UPDATE)
    public R suspendProcessDefinitionById(String processDefinitionId, boolean suspendProcessInstances) {
        repositoryService.suspendProcessDefinitionById(processDefinitionId, suspendProcessInstances, null);
        return R.ok(true);
    }

    @GetMapping("activateProcessDefinitionById")
    @ApiOperation(value = "流程激活")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", required = true),
            @ApiImplicitParam(name = "activateProcessInstances", value = "是激活起流程实例")
    })
    @Log(title = "流程激活", businessType = BusinessType.UPDATE)
    public R activateProcessDefinitionById(String processDefinitionId, boolean activateProcessInstances) {
        repositoryService.activateProcessDefinitionById(processDefinitionId, activateProcessInstances, null);
        return R.ok(true);
    }

    @PostMapping("endProcessByTaskId")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "taskId", value = "任务id", required = true),
            @ApiImplicitParam(name = "opinion", value = "终止原因")
    })
    @ApiOperation(value = "终止一个流程实例")
    @Log(title = "流程终止", businessType = BusinessType.UPDATE)
    @AutoSetMineCode
    public R endProcess(String taskId, String opinion, @RequestBody ExamineVo examineVo, String mineCode) {
        Task task = taskService.createTaskQuery().taskId(taskId).includeProcessVariables().singleResult();

        if (task == null) {
            return R.fail("未找到对应的任务");
        }
        examineVo.getNodeParams().put("end", "未通过");
        taskService.setVariablesLocal(task.getId(), examineVo.getNodeParams());
        taskService.complete(task.getId(), examineVo.getProcessParams());
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        List<String> collect = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list().stream().map(Task::getId).collect(Collectors.toList());
//        List<Task> list = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        if (!collect.isEmpty()) {
            collect.forEach(s -> {
                processEngineConfiguration.getManagementService().executeCommand(new DeleteTaskCommand(s));
            });
            runtimeService.deleteProcessInstance(task.getProcessInstanceId(), opinion);
        }
        UserVo userById = remoteUserService.getUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
        if (userById != null) {
            WeChartBaseMessage msg = new WeChartBaseMessage();
            String content = "您发起的流程——" + historicProcessInstance.getName() + ",审批被拒绝，详情请登陆系统查看。";
            msg.setContent(content);
            msg.setPassword("hn@2022");
            msg.setToUsers(userById.getUserName());
            try {
                remoteMineInfoService.sendBaseMessage(msg);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            processDetail(historicProcessInstance, mineCode);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("流程保存业务表异常：" + e.getMessage());
        }

        return R.ok("流程已结束", new HashMap() {{
            put("businessKey", historicProcessInstance.getBusinessKey());
            put("taskName", task.getName());
        }});
    }

    @GetMapping("getMyStart")
    @ApiOperation(value = "我发起的流程")
    @Log(title = "查询我的发起流程", businessType = BusinessType.OTHER)
    public R<ResponsePage<MyStartProcessDto>> getMyStart(String processDefinitionId, @RequestParam(defaultValue = "0") int pageNum, @RequestParam(defaultValue = "10") int pageSize) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        if (StringUtils.isNotBlank(processDefinitionId)) {
            historicProcessInstanceQuery = historicProcessInstanceQuery.processDefinitionId(processDefinitionId);
        }
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.startedBy(LoginHelper.getUserId() + "").orderByProcessInstanceStartTime().desc().listPage(pageNum < 0 ? 0 : (pageNum * pageSize), pageSize);
        List<MyStartProcessDto> list = new ArrayList<>();
        for (HistoricProcessInstance instance : historicProcessInstances) {
            MyStartProcessDto dto = new MyStartProcessDto();
            dto.setEndTime(instance.getEndTime());
            dto.setStartTime(instance.getStartTime());
            dto.setProcessInstanceId(instance.getId());
            dto.setProcessName(instance.getName());
            if (instance.getEndTime() != null) {
                if (instance.getDeleteReason() == null) {
                    dto.setCurrentTask("已完成");
                    dto.setProcessStatus("已结束");
                } else {
                    if (instance.getDeleteReason().equals("用户撤回")) {
                        //设置节点名称
                        //dto.setCurrentTask("撤回");
                        //获取历史审批节点list
                        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
                        //查询 actinst表，条件：根据 InstanceId 查询
                        instanceQuery.processInstanceId(instance.getId());
                        //增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
                        instanceQuery.orderByHistoricActivityInstanceStartTime().desc();
                        //获取节点列表
                        List<HistoricActivityInstance> list1 = instanceQuery.list();
                        //降序排列后第一个为终止节点
                        //设置节点名称
                        dto.setCurrentTask(list1.get(0).getActivityName());
                        dto.setProcessStatus("已撤销");
                        dto.setDeleteReason(instance.getDeleteReason());
                    }
                }
            } else {
                Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
                dto.setCurrentTask(task.getName());
                dto.setCurrentTaskId(task.getId());
                if (task.getName().equals("发起") || task.getName().equals("发起审批") || task.getName().equals("技术负责人填报")) {
                    dto.setProcessStatus("暂存中");
                } else {
                    dto.setProcessStatus("进行中");
                }
            }
            list.add(dto);
        }
        return R.ok(new ResponsePage<MyStartProcessDto>(list, historicProcessInstanceQuery.count()));
    }

    @GetMapping("getAllDefinitionProcess")
    @ApiOperation(value = "获取所有的已部署流程")
    @Log(title = "查询所有已部署流程", businessType = BusinessType.OTHER)
    public R<List<ProcessDefinitionDto>> getAllDefinitionProcess() {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
        List<ProcessDefinitionDto> definitionDtos = new ArrayList<>();
        for (ProcessDefinition definition : list) {
            ProcessDefinitionDto dto = new ProcessDefinitionDto();
            dto.setId(definition.getId());
            dto.setName(definition.getName());
            definitionDtos.add(dto);
        }
        return R.ok(definitionDtos);
    }

    @GetMapping("myActivityHisByProcessInstanceId")
    @ApiOperation(value = "获取流程审批历史信息")
    @Log(title = "查询流程审批历史信息", businessType = BusinessType.OTHER)
    public R<List<HistoricActivityInstance>> myActivityHis(String processInstanceId) {
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
        //查询 actinst表，条件：根据 InstanceId 查询
        instanceQuery.processInstanceId(processInstanceId);
        //增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
        return R.ok(instanceQuery.list());
    }

    @GetMapping("withdraw")
    @ApiOperation(value = "撤回")
    @Log(title = "流程撤回", businessType = BusinessType.UPDATE)
    @AutoSetMineCode
    public R withdraw(String processInstanceId, String mineCode) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance == null) {
            return R.fail("流程不存在或已结束");
        }
        runtimeService.deleteProcessInstance(processInstanceId, "用户撤回");
        myProcessRepository.deleteById(mineCode + processInstanceId);
//        historyService.deleteHistoricTaskInstance(processInstanceId);
//        historyService.deleteHistoricProcessInstance(processInstanceId);
        return R.ok("撤回成功");
    }

    @GetMapping("deleteFinish")
    @ApiOperation(value = "流程删除（已完成流程）")
    @Log(title = "流程删除（已完成流程）", businessType = BusinessType.UPDATE)
    @AutoSetMineCode
    public R deleteFinish(String processInstanceId, String mineCode) {
//        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//        if (processInstance == null) {
//            return R.fail("流程不存在或已结束");
//        }
//        runtimeService.deleteProcessInstance(processInstanceId, "用户删除");
        historyService.deleteHistoricTaskInstance(processInstanceId);
        historyService.deleteHistoricProcessInstance(processInstanceId);
        myProcessRepository.deleteById(mineCode + processInstanceId);
        return R.ok("删除成功");
    }

    @GetMapping("delete")
    @ApiOperation(value = "流程删除（正在执行流程）")
    @Log(title = "流程删除", businessType = BusinessType.UPDATE)
    @AutoSetMineCode
    public R delete(String processInstanceId, String mineCode) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance == null) {
            return R.fail("流程不存在或已结束");
        }
        runtimeService.deleteProcessInstance(processInstanceId, "用户删除");
        historyService.deleteHistoricTaskInstance(processInstanceId);
        historyService.deleteHistoricProcessInstance(processInstanceId);
        myProcessRepository.deleteById(mineCode + processInstanceId);
        return R.ok("删除成功");
    }


    @GetMapping("hisForm")
    @ApiOperation(value = "获取历史填报信息")
    @Log(title = "查询历史填报信息", businessType = BusinessType.OTHER)
    public R<List<HistorFormDataDto>> HisForm(String processInstanceId) {
        List<HistoricTaskInstance> list1 = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceStartTime().asc().list();
        List<HistorFormDataDto> taskFormDataList = new ArrayList<>();
        Map<String, String> map = null;
        for (HistoricTaskInstance taskInstance : list1) {

            if (map == null) {
                map = getFormProperty(taskInstance.getProcessDefinitionId());
            }
            HistorFormDataDto dataDto = new HistorFormDataDto();
            if (taskInstance.getEndTime() != null) {
                dataDto.setEnd(true);
            } else {
                dataDto.setEnd(false);
            }
            dataDto.setName(taskInstance.getName());
            List<HistoricDetail> list = historyService.createHistoricDetailQuery().taskId(taskInstance.getId()).formProperties().list();

            for (HistoricDetail detail : list) {
                HistoricDetailVo vo = new HistoricDetailVo();
                HistoricFormPropertyEntityImpl impl = (HistoricFormPropertyEntityImpl) detail;
                BeanUtils.copyProperties(impl, vo);

                vo.setName(map.get(impl.getPropertyId()));
                dataDto.getDetails().add(vo);
            }

            taskFormDataList.add(dataDto);
//            }
        }
        return R.ok(taskFormDataList);
    }

    public Map<String, String> getFormProperty(String processDefinitionId) {
        Map<String, String> map = new HashMap<>();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        for (Process process : bpmnModel.getProcesses()) {
            List<UserTask> flowElementsOfType = process.findFlowElementsOfType(UserTask.class);
            for (UserTask userTask : flowElementsOfType) {
                List<FormProperty> formProperties = userTask.getFormProperties();
                for (FormProperty formProperty : formProperties) {
                    map.put(formProperty.getId(), formProperty.getName());
                }
            }
        }
        return map;
    }

    @GetMapping("getAll")
    @ApiOperation(value = "查询全部流程")
    @Log(title = "查询全部流程", businessType = BusinessType.OTHER)
    public R<ResponsePage<MyStartProcessDto>> getAll(String processDefinitionId, @RequestParam(defaultValue = "0") int pageNum, @RequestParam(defaultValue = "10") int pageSize) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        if (StringUtils.isNotBlank(processDefinitionId)) {
            historicProcessInstanceQuery = historicProcessInstanceQuery.processDefinitionId(processDefinitionId);
        }
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.orderByProcessInstanceStartTime().desc().listPage(pageNum < 0 ? 0 : (pageNum * pageSize), pageSize);
        List<MyStartProcessDto> list = new ArrayList<>();
        for (HistoricProcessInstance instance : historicProcessInstances) {
            MyStartProcessDto dto = new MyStartProcessDto();
            UserVo userById = remoteUserService.getUserById(Long.parseLong(instance.getStartUserId()));
            if (userById != null) {
                dto.setStartUser(userById.getUserName());
                //发起人姓名
                dto.setStartUserName(userById.getNickName());
            }
            dto.setEndTime(instance.getEndTime());
            dto.setStartTime(instance.getStartTime());
            dto.setProcessInstanceId(instance.getId());
            dto.setProcessName(instance.getName());
            if (instance.getEndTime() != null) {
                if (instance.getDeleteReason() == null) {
                    dto.setCurrentTask("已完成");
                    dto.setProcessStatus("已结束");
                } else {
                    if (instance.getDeleteReason().equals("用户撤回")) {
                        //设置节点名称
                        //dto.setCurrentTask("撤回");
                        //获取历史审批节点list
                        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
                        //查询 actinst表，条件：根据 InstanceId 查询
                        instanceQuery.processInstanceId(instance.getId());
                        //增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
                        instanceQuery.orderByHistoricActivityInstanceStartTime().desc();
                        //获取节点列表
                        List<HistoricActivityInstance> list1 = instanceQuery.list();
                        //降序排列后第一个为终止节点
                        //设置节点名称
                        dto.setCurrentTask(list1.get(0).getActivityName());

                        //设置节点状态
                        dto.setProcessStatus("已撤销");
                        dto.setDeleteReason(instance.getDeleteReason());
                    }
                }
            } else {
                Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
                dto.setCurrentTask(task.getName());
                dto.setCurrentTaskId(task.getId());
                if (task.getName().equals("发起") || task.getName().equals("发起审批") || task.getName().equals("技术负责人填报")) {
                    dto.setProcessStatus("暂存中");
                } else {
                    dto.setProcessStatus("进行中");
                }
            }
            list.add(dto);
        }
        return R.ok(new ResponsePage<MyStartProcessDto>(list, historicProcessInstanceQuery.count()));
    }
    @GetMapping("getCodeByProcessDefinitionId")
    @ApiOperation(value = "根据定义id获取编号")
    public R<String> getCodeByProcessDefinitionId(String processDefinitionId) {
        String codeString = "";
        //根据流程定义获取定义信息
        R<List<ProcessDefinitionDto>> allDefinitionProcess = getAllDefinitionProcess();
        if (allDefinitionProcess.getData().size() > 0) {
            List<ProcessDefinitionDto> data = allDefinitionProcess.getData();
            //循环查询 获取符合要求的编号前缀
            for (ProcessDefinitionDto datum : data) {
//                String[] split = datum.getId().split(":");
//                //获取id 规则：危险点预控:1:32679
//                String id = split[split.length - 1];
                if (datum.getId().equals(processDefinitionId)) {
                    //获取今天的日期
                    LocalDate today = LocalDate.now();
                    //获取明天的日期
                    LocalDate tomorrow = today.plusDays(1);
                    //日期格式
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
//                    String formattedDate = today.format(formatter);
                    String formattedDate = tomorrow.format(formatter);

                    //定义名称
                    String name = datum.getName();
                    if (name.contains("有限空间作业")) {
                        codeString = "gty-yxkjzy-" + formattedDate+"-";
                        //退出for循环
                        break;
                    } else if (name.contains("危险点预控")) {
                        codeString = "gty-wxdyk-" + formattedDate+"-";
                        break;
                    } else if (name.contains("高空作业")) {
                        codeString = "gty-gkzy-" + formattedDate+"-";
                        break;
                    } else if (name.contains("电气焊作业")) {
                        codeString = "gty-dqhzy-" + formattedDate+"-";
                        break;
                    } else if (name.contains("起吊作业")) {
                        codeString = "gty-qdzy-" + formattedDate+"-";
                        break;
                    } else if (name.contains("工作票")) {
                        codeString = "gty-gzp-" + formattedDate+"-";
                        break;
                    } else if (name.contains("经营计划")) {
                        codeString = "gty-jyjh-" + formattedDate+"-";
                        break;
                    } else {
                        codeString = "gty-xxxx-" + formattedDate+"-";
                        break;
                    }
                }
            }
            //查询当前数据，计算已存在的数据量 推算加1
            R<ResponsePage<MyStartProcessDto>> all = this.getAll(processDefinitionId, 0, 10);
            if (all.getData().getPageData().size() > 0) {
            //获取第一条数据
                if (all.getData().getPageData().get(0).getProcessInstanceId() != null) {
                    MyStartProcessDto myStartProcessDto = all.getData().getPageData().get(0);
                    //获取开始时间
                    Date startTime = myStartProcessDto.getStartTime();
                    //判断时间是否等于今天
                    if (startTime != null) {
                        LocalDate start = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        LocalDate nowDate = LocalDate.now();
                        if (start.equals(nowDate)) {
                            //时间相等 证明今天已经有存在的数据
                            //获取当前记录的编码
                            String processInstanceId = myStartProcessDto.getProcessInstanceId();
                            //根据实例id获取历史信息
                            R<List<HistorFormDataDto>> listR = this.HisForm(processInstanceId);
                            //获取发起填报信息
                            HistorFormDataDto historFormDataDto = listR.getData().get(0);
                            for (HistoricDetailVo t : historFormDataDto.getDetails()) {
                                //获取编码字段
                                if ("code_input".equals(t.getPropertyId())) {
                                    //获取参数值
                                    String propertyValue = t.getPropertyValue();
                                    if (StringUtils.isNotEmpty(propertyValue)) {
                                        //提取最后一个“-”后面的数字  规则：gty-yxkj-20240219-906
                                        String numberString = propertyValue.substring(propertyValue.lastIndexOf("-") + 1);
                                        //将字符转为数字 加1
                                        //判断最后一部分数字是否小于十   小于十就加 01
                                        //定义起始数字
//                                        int startNumber = 1;
                                        int startNumber = Integer.parseInt(numberString) +1;
                                        //定义数字位数 2位小数
                                        int numberOfDigits = 2;
                                            String number = String.format("%0" + numberOfDigits + "d", startNumber);
                                        codeString = codeString + number;
                                        return R.ok("获取成功", codeString);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        //默认为第一条
        return R.ok("获取成功", codeString = codeString + "01");
    }

    @GetMapping("extractionData")
    @ApiOperation(value = "提取工作流数据")
    @Transient
    public R extractionData(String mineCode) {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
        List<MyProcess> processList = new ArrayList<>();
        for (ProcessDefinition definition : list) {
//            processList.addAll(processDetail(definition.getId(),definition.getName(),mineCode));
            List<HistoricProcessInstance> instances = historyService.createHistoricProcessInstanceQuery().processDefinitionId(definition.getId()).list();
            for (HistoricProcessInstance instance : instances) {
                processList.add(processDetail(instance, mineCode));
            }
        }
        return R.ok(processList.size());
    }

    public MyProcess processDetail(HistoricProcessInstance instance, String mineCode) {
        MyProcess process = new MyProcess();
        process.setId(mineCode + instance.getId());
        process.setProType(instance.getProcessDefinitionName());
        process.setProName(instance.getName());
        process.setMineCode(mineCode);
        UserVo userById = remoteUserService.getUserById(Long.parseLong(instance.getStartUserId()));
        if (userById != null) {
            process.setStartUser(userById.getNickName());
            process.setUserNo(userById.getUserName());
        }
        process.setEndTime(instance.getEndTime());
        process.setStartTime(instance.getStartTime());
        if (instance.getEndTime() != null) {
            if (instance.getDeleteReason() == null) {
                process.setCurrentTask("已完成");
                process.setProcessStatus("已结束");
            } else {
                if (instance.getDeleteReason().equals("用户撤回")) {
                    //设置节点名称
                    //dto.setCurrentTask("撤回");
                    //获取历史审批节点list
                    HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
                    //查询 actinst表，条件：根据 InstanceId 查询
                    instanceQuery.processInstanceId(instance.getId());
                    //增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
                    instanceQuery.orderByHistoricActivityInstanceStartTime().desc();
                    //获取节点列表
                    List<HistoricActivityInstance> list1 = instanceQuery.list();
                    //降序排列后第一个为终止节点
                    //设置节点名称
                    process.setCurrentTask(list1.get(0).getActivityName());

                    //设置节点状态
                    process.setProcessStatus("已撤销");
                    process.setDeleteReason(instance.getDeleteReason());
                }
            }
        } else {
            Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
            process.setCurrentTask(task.getName());
            process.setCurrentTaskId(task.getId());
            if (task.getName().equals("发起") || task.getName().equals("发起审批") || task.getName().equals("技术负责人填报")) {
                process.setProcessStatus("暂存中");
            } else {
                process.setProcessStatus("进行中");
            }
        }
        List<HistoricTaskInstance> taskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(instance.getId()).orderByHistoricTaskInstanceStartTime().asc().list();
        Process processById = repositoryService.getBpmnModel(instance.getProcessDefinitionId()).getProcessById(instance.getProcessDefinitionKey());
        List<UserTask> flowElementsOfType = processById.findFlowElementsOfType(UserTask.class);
        for (UserTask userTask : flowElementsOfType) {
            MyTask task = new MyTask();
            task.setId(mineCode + instance.getId() + userTask.getId());
            task.setName(userTask.getName());
//            if (StringUtils.isNotBlank(userTask.getAssignee())) {
//                UserVo userVo = remoteUserService.getUserById(Long.parseLong(userTask.getAssignee()));
//                if (userVo != null) {
//                    task.setAssignee(userVo.getNickName());
//                    task.setAssigneeNo(userVo.getUserName());
//                }
//            }
            List<FormProperty> formProperties = userTask.getFormProperties();
            for (FormProperty formProperty : formProperties) {
                if (formProperty.getName() == null) {
                    continue;
                }
                MyForm form = new MyForm();
                form.setId(task.getId() + formProperty.getId());
                form.setName(formProperty.getName());
                form.setPropertyId(formProperty.getId());
                task.getForms().add(form);
            }
            process.getTasks().add(task);
        }

        for (HistoricTaskInstance taskInstance : taskInstances) {
            MyTask task = getMyTask(process, mineCode + instance.getId() + taskInstance.getTaskDefinitionKey());
            task.setId(mineCode + taskInstance.getId());
            if (StringUtils.isNotBlank(taskInstance.getAssignee())) {
                UserVo userVo = remoteUserService.getUserById(Long.parseLong(taskInstance.getAssignee()));
                if (userVo != null) {
                    task.setAssignee(userVo.getNickName());
                    task.setAssigneeNo(userVo.getUserName());
                }
            }

            task.setName(taskInstance.getName());
            task.setStartDate(taskInstance.getStartTime());
            task.setCompletionDate(taskInstance.getEndTime());

            List<HistoricDetail> forms = historyService.createHistoricDetailQuery().taskId(taskInstance.getId()).formProperties().list();
            for (HistoricDetail detail : forms) {
                HistoricFormPropertyEntityImpl impl = (HistoricFormPropertyEntityImpl) detail;
                MyForm form = getMyForm(task, mineCode + instance.getId() + taskInstance.getTaskDefinitionKey() + impl.getPropertyId());
                form.setId(task.getId() + impl.getId());
                form.setValue(impl.getPropertyValue());
                if(form.getPropertyId()!=null&&form.getPropertyId().endsWith("userseletct")&&StringUtils.isNotBlank(impl.getPropertyValue())) {
                    UserVo userVo = remoteUserService.getUserById(Long.parseLong(impl.getPropertyValue()));
                    if (userVo != null) {
                        form.setValue(userVo.getNickName());
                    }
                }
            }
        }

        return myProcessRepository.save(process);
    }

    public MyForm getMyForm(MyTask task, String id) {
        for (MyForm form : task.getForms()) {
            if (id.equals(form.getId())) {
                return form;
            }
        }
        return new MyForm();
    }

    public MyTask getMyTask(MyProcess process, String id) {
        for (MyTask task : process.getTasks()) {
            if (id.equals(task.getId())) {
                return task;
            }
        }
        return new MyTask();
    }
    @GetMapping("/export")
    @ApiOperation(value = "导出审批单")
    public void export(String processInstanceId, @ApiIgnore HttpServletResponse response) throws Exception {
        InputStream resourceAsStream = ActivitiController.class.getClassLoader().getResourceAsStream("processes/license.xml");
        com.aspose.words.License license = new com.aspose.words.License();
        license.setLicense(resourceAsStream);
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(instance.getProcessDefinitionId()).singleResult();
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(pd.getDeploymentId()).singleResult();
        String templatePath = "processes/";
        String fileName = deployment.getName()+".docx";
//        if ("有限空间作业".equals(deployment.getName())) {
//            templatePath = "processes\\有限空间作业.docx";
//        }
        BpmnModel bpmnModel = repositoryService.getBpmnModel((instance.getProcessDefinitionId()));
        List<UserTask> flowElementsOfType = bpmnModel.getProcesses().get(0).findFlowElementsOfType(UserTask.class);
        List<FormProperty> formProperties = new ArrayList<>();
        for (UserTask userTask : flowElementsOfType) {
            for(FormProperty formProperty:userTask.getFormProperties()) {
                FormProperty formProperty1 = new FormProperty();
                formProperty1.setValues(formProperty);
                formProperties.add(formProperty1);
            }
        }
        Map<String, FormProperty> collect = formProperties.stream().collect(Collectors.toMap(s -> s.getId(), s -> s, (o, o1) -> o1));
        List<HistoricTaskInstance> list1 = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
        for (HistoricTaskInstance taskInstance : list1) {
            List<HistoricDetail> list = historyService.createHistoricDetailQuery().taskId(taskInstance.getId()).formProperties().list();
            for (HistoricDetail detail : list) {
                HistoricFormPropertyEntityImpl impl = (HistoricFormPropertyEntityImpl) detail;
                FormProperty formProperty = collect.get(impl.getPropertyId());
                if (formProperty != null) {
                    formProperty.setDefaultExpression(impl.getPropertyValue());
                }
            }
        }
        //读取文档数据 路径名称+文件名称
        Document doc = new Document(ActivitiController.class.getClassLoader().getResourceAsStream(templatePath+fileName));
//        Document doc = new Document("C:\\soft\\hnms-stack\\hnms-biz-modules\\hnms-biz-production\\hnms-biz-activiti\\src\\main\\resources\\processes\\有限空间作业.docx");
        for (Map.Entry<String, FormProperty> entry : collect.entrySet()) {
            String key = entry.getKey();
            FormProperty value = entry.getValue();
            if (key.endsWith("userseletct")) {
                //如果是用户列表结尾
                if (StringUtils.isNotBlank(value.getDefaultExpression())) {
//                    Optional<SysUser> byId = sysUserRespoistory.findById(Long.parseLong(value.getDefaultExpression()));
                    UserVo byId = remoteUserService.getUserById(Long.parseLong(value.getDefaultExpression()));
                    if (byId !=null) {
                        doc.getRange().replace("${" + key + "}", byId.getNickName(), false, false);
                    }
                }
            }
            //判断id是否是radio结尾
            if (key.endsWith("radio")) {
                if (StringUtils.isNotBlank(value.getDefaultExpression())) {
                    if ("true".equals(value.getDefaultExpression())) {
                        doc.getRange().replace("${" + key + "}",  "是 ☑ 否 □", false, false);
                    } else {
                        doc.getRange().replace("${" + key + "}",  "是 □ 否 ☑", false, false);
                    }
                } else {
                    doc.getRange().replace("${" + key + "}",   "是 □ 否 □", false, false);
                }


            } else if (key.endsWith("signature")) {
                //如果是以signature结尾  证明是个签名图片
                //http://oss.vrie.top/2024/01/30/95a0eb4e8d844f63ba3ef1443d43b896.jpg
                //判断值不为空
                if (StringUtils.isNotEmpty(value.getDefaultExpression())) {
//                    BufferedImage bufferedImage=new BufferedImage()
                    // 创建用于加载图片的输入流
                    doc.getRange().replace(Pattern.compile("\\$\\{" + key + "\\}"), new ReplaceAndInsertImage(value.getDefaultExpression()), false);
                }else {
                    doc.getRange().replace("${" + key + "}", "", false, false);
                }
            } else if (key.endsWith("file")) {
                //如果是以file结尾  证明是文件列表
                //eg:"[{\"status\":\"success\",\"name\":\"组 78579.png\",\"size\":269258,\"percentage\":100,\"uid\":1708332502193,\"raw\":{\"uid\":1708332502193},\"response\":{\"code\":200,\"msg\":\"操作成功\",\"data\":{\"ossId\":\"1759500168041369602\",\"url\":\"http://oss.vrie.top/2024/02/19/acd8754da26c4ff2b3225a1c32be4171.png\",\"fileName\":\"组 78579.png\"}}},{\"status\":\"success\",\"name\":\"实际服务器配置.docx\",\"size\":793473,\"percentage\":100,\"uid\":1708332527601,\"raw\":{\"uid\":1708332527601},\"response\":{\"code\":200,\"msg\":\"操作成功\",\"data\":{\"ossId\":\"1759500278498365442\",\"url\":\"http://oss.vrie.top/2024/02/19/3ccce34cd7674f4394c9f102dc2973d8.docx\",\"fileName\":\"实际服务器配置.docx\"}}}]"
                if (value.getDefaultExpression() != null) {
                    ObjectMapper objectMapper = new ObjectMapper();
                    JsonNode jsonNode = objectMapper.readTree(value.getDefaultExpression());

                    String fileNameString = "";
                    for (JsonNode node : jsonNode) {
//                        String upDateFileName = node.get("response").get("data").get("fileName").asText();
                        //有上传失败的可能性 不选择响应数据 从基本数据中获取
                        //eg:[{"status":"success","name":"2-开工许可票.jpg","size":3039690,"percentage":100,"uid":1708478796938,"raw":{"uid":1708478796938},"response":{"code":500,"msg":"404 NOT_FOUND","data":null}}]
                        String upDateFileName = node.get("name").asText();
                        //获取文件名称
//                    System.out.println("fileName: " + upDateFileName);
                        fileNameString = fileNameString + upDateFileName + "，";
                    }
                    //去除最后一个逗号
                    if (fileNameString.endsWith("，")) {
                        fileNameString = fileNameString.substring(0, fileNameString.length() - 1);
                    }
                    doc.getRange().replace("${" + key + "}", fileNameString, false, false);

                } else {
                    //值为空
                    doc.getRange().replace("${" + key + "}", "", false, false);

                }
            } else if (key.endsWith("dateAndDate")) {
                //如果是以dateAndDate结尾
                //处理json格式数据时间   ["2024-02-01 00:00:00","2024-02-08 00:00:00"]
                if (value.getDefaultExpression() != null) {
                    //值不为空
                    try {
                        ObjectMapper objectMapper = new ObjectMapper();
                        String[] array = objectMapper.readValue(value.getDefaultExpression(), String[].class);
                        // 输出转换后的对象
                        //开始时间
                        String startDateString = array[0];
                        //结束时间
                        String endDateString = array[1];
                        doc.getRange().replace("${" + key + "}",startDateString + "至" + endDateString, false, false);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    doc.getRange().replace("${" + key + "}", "", false, false);
                }
            } else {
                doc.getRange().replace("${" + key + "}", value.getDefaultExpression() == null ? "" : value.getDefaultExpression(), false, false);
            }
        }
//        String startUserId = instance.getStartUserId();
//        if (StringUtils.isNotBlank(startUserId)) {
//            UserVo byId = remoteUserService.getUserById(Long.parseLong(startUserId));
//            if (byId != null) {
//
//                doc.getRange().replace("${initiator}", byId.getNickName(), false, false);
//            }
//        }
        try {
            String encodedFileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
            // .doc 格式
//            response.setContentType("application/msword");
            //docx格式
            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            OutputStream os = response.getOutputStream();
            doc.save(os, 10);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 上传OSS对象存储
     */
    @SneakyThrows
    @ApiOperation("上传签名图片")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "图片文件", paramType = "query", dataTypeClass = File.class, required = true)
    })
    @PostMapping("/uploadSignature")
    public R<SysFile> uploadSignature(@RequestPart("file") MultipartFile file) {
        if (ObjectUtil.isNull(file)) {
            throw new ServiceException("上传文件不能为空");
        }
        // 检查上传文件的类型
        if (!file.getContentType().startsWith("image/")) {
            throw new HuaNengException(Constants.FAIL, "只能上传图片文件");
        }
        InputStream inputStream = null;
        BufferedImage bufferedImage = null;
        BufferedImage signaturePictureBufferedImage = null;
        try {
            //获取文件输入流
            inputStream = file.getInputStream();
             bufferedImage = ImageIO.read(inputStream);
             // 签名图片处理
            signaturePictureBufferedImage = SignaturePictureProcessUtil.signaturePictureProcess(bufferedImage);
            inputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(signaturePictureBufferedImage, "PNG", byteArrayOutputStream);
        byte[] bytes = byteArrayOutputStream.toByteArray();
        //远程调用处理上传文件
        SysFile upload = remoteFileService.upload("", file.getOriginalFilename(), file.getContentType(), bytes);
        if (upload == null) {
            return R.fail("上传失败");
        }
        return R.ok(upload);
    }
}
